package com.nulldev.util.crypto.api2.encryptors;

import java.math.BigInteger;
import java.nio.charset.Charset;

import com.nulldev.util.crypto.api2.Cryptable;
import com.nulldev.util.encoding.base64.Base64;
import com.nulldev.util.other.CharsetUtil;

public class SafeXOR extends Cryptable{

	public SafeXOR() {
		super("XOR.safe");
	}

	@Override
	public String encrypt(String object, String pass) {
		return this.encrypt(object, pass, CharsetUtil.getCharset());
	}

	@Override
	public String decrypt(String object, String pass) {
		return this.decrypt(object, pass, CharsetUtil.getCharset());
	}
	
	@Override
	public String encrypt(String object, String pass, Charset charset) {
		return toHexString(xorWithKey(object.getBytes(charset), pass.getBytes()));
	}

	@Override
	public String decrypt(String object, String pass, Charset charset) {
		return new String(xorWithKey(toByteArray(object), pass.getBytes()));
	}

    private static byte[] xorWithKey(byte[] a, byte[] key) {
        byte[] out = new byte[a.length];
        for (int i = 0; i < a.length; i++) {
            out[i] = (byte) (a[i] ^ key[i%key.length]);
        }
        return out;
    }

    private static byte[] base64Decode(final String s) {
    	return Base64.decodeBase64(s);//Base64Utils.encodeString(s).getBytes(CharsetUtil.getCharset());
    	//try {
    	//	return java.util.Base64.getDecoder().decode(s.getBytes(CharsetUtil.getCharset()));
    	//}catch (IllegalArgumentException e) {
    	//	throw new RuntimeException("[CryptoUtil] Failed to decode '" + s + "'. [" + e.getClass().getName() + " -> " + e.getMessage() + "]");
    	//}
    }

    private static String base64Encode(final byte[] bytes) {
    	return new String(Base64.encodeBase64String(bytes));//Base64Utils.decodeString(new String(bytes, CharsetUtil.getCharset()));
    	//throw new UnsupportedOperationException("Unsupported Java release.");
		//byte[] new_string = java.util.Base64.getEncoder().encode(bytes);
		//return new String(new_string, CharsetUtil.getCharset());
    }
    
    public String toHexString(byte[] bytes) {
    	final StringBuilder sb = new StringBuilder();
     	for (byte b : bytes) {
     		sb.append(String.format("%02X", b));
     	}
     	return sb.toString();
    }
    
    public String toHex(String arg) {
        return String.format("%02x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
    }
    
    public byte[] toByteArray(String s) {
    	int len = s.length();
     	byte[] data = new byte[len / 2];
     	for (int i = 0; i < len; i += 2) {
     		data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
     	}
     	return data;
    }
    
    public static String unHex(String arg) {        

        String str = "";
        for(int i=0;i<arg.length();i+=2)
        {
            String s = arg.substring(i, (i + 2));
            int decimal = Integer.parseInt(s, 16);
            str = str + (char) decimal;
        }       
        return str;
    }
}

